/**
通信兵管理者，负责维持一个通信兵的列表，并且从列表里找出一个空闲的来派他出去，如果找不出空闲的]
则要新生成新的通信兵了，有10个就可以了，不够了就加5个

注意超时处理出错重连和重试次数是在SendAndLoad里设置的
*/

package kgame5.kio.remoting {
import kgame5.kutil.*;

import flash.events.*;
import flash.net.*;

public class SignalmenManager extends EventDispatcher{
	//_____________________static_____________________
	//事件类型
	public static const
		EVENTTYPE_COMMOK:String="EVENTTYPE_COMMOK",
		EVENTTYPE_COMMFAIL:String="EVENTTYPE_COMMFAIL",
		//EVENTTYPE_COMMTIMEOUT:String="EVENTTYPE_COMMTIMEOUT",
		EVENTTYPE_AUTORETRY:String="EVENTTYPE_AUTORETRY";
	
	//_____________________propetry_____________________
	//容量
	private var Capacity:int=10;
	//维持signalman的列表
	private var aSignalmenPoll:Array=null;
	//
	private var nc_dest : NetConnection = null;
	
	private var 
		gatewayUrl:String,//"http://192.168.0.118:3000/gateway"
		servletPath:String;//"/.MyServlet",servlet是可以根据url里的指定的名字来加载指定的Servlet的
			
	//_____________________method_______________________
	public function SignalmenManager(p_gatewayUrl:String,p_servletPath:String){
		
		gatewayUrl=p_gatewayUrl;
		servletPath=p_servletPath;
		
		//--填充SignalmenPoll
		aSignalmenPoll=new Array();
		var i:int;
		for(i=0;i<Capacity;i++){
			aSignalmenPoll.push(new Signalman(servletPath,this));
		}
		//
		nc_dest=new NetConnection();
		
		nc_dest.objectEncoding = ObjectEncoding.AMF0;//使用as1和as2兼容的amf编码
		
		nc_dest.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
		nc_dest.addEventListener(IOErrorEvent.IO_ERROR , ioErrorHandler);
		nc_dest.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
		nc_dest.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);

		nc_dest.connect(gatewayUrl);//"http://192.168.0.109/gateway"

		trace2("SignalmenManager:"+gatewayUrl+" "+servletPath);
	}
	//从通信兵列表里找出一个空闲的，并派他完成任务
	public function SendAndLoad(p_package : Object,
									bNeedAutoRetry:Boolean=true,
									Timeout_Dur:int=5*60*1000,Autoretry_Dur:int=30*1000,MaxFailTimes:int=10
								){
		trace2("SignalmenManager.SendAndLoad: pid:"+p_package.iPackageID+" "+bNeedAutoRetry+" "+Timeout_Dur/1000+" "+Autoretry_Dur/1000+" "+MaxFailTimes);
		var sm:Signalman=getFreeSignalman();
		sm.SendAndLoad(nc_dest,p_package,
							bNeedAutoRetry,
							Timeout_Dur,Autoretry_Dur,MaxFailTimes);
	}
	//从队列里找出一个空闲的通信兵
	private function getFreeSignalman():Signalman{
		var sm:Signalman;
		
		//找到一个可用的并标志出可用
		var i:int;
		var len:int=aSignalmenPoll.length;
		for(i=0;i<len;i++){
			sm=aSignalmenPoll[i];
			if(sm.isFree()){
				//T.p("找到一个signalmen:"+i+"/"+aSignalmenPoll.length);
				return sm;
			}
		}
		
		//如果找不到，则新建立一个
		sm=new Signalman(servletPath,this);
		aSignalmenPoll.push(sm);
		T.p("新生成一个signalmam:"+aSignalmenPoll.length);
		return sm;
	}
	
	//--
	private function asyncErrorHandler(e:AsyncErrorEvent){
		T.p("SignalmenManager.asyncErrorHandler");
	}
	private function ioErrorHandler(e:IOErrorEvent){
		T.p("SignalmenManager.ioErrorHandler");
	}
	private function netStatusHandler(e:NetStatusEvent){
		T.p("SignalmenManager.netStatusHandler",e.type,e.info);
	}
	private function securityErrorHandler(e:SecurityErrorEvent){
		T.p("SignalmenManager.securityErrorHandler");
	}
	//////////////
	
	public function notifyCommOK (result:Object){//被服务器返回的结果r.iFuncInfo,r.funcStatus等
		var ke:KEvent=new KEvent(EVENTTYPE_COMMOK,
			{
				result:result
			}
		);
		this.dispatchEvent(ke);
	}
	public  function notifyCommFail (myPackage:Object){
		var ke:KEvent=new KEvent(EVENTTYPE_COMMFAIL,
			{
				myPackage:myPackage
			}
		);
		this.dispatchEvent(ke);
	}
	/*
	public  function notifyCommTimeout (myPackage:Object){
		var ke:KEvent=new KEvent(EVENTTYPE_COMMTIMEOUT,
			{
				myPackage:myPackage
			}
		);
		this.dispatchEvent(ke);
	}
	//*/
	public  function notifyAutoRetry(myPackage:Object){//失败后在自动重连
		var ke:KEvent=new KEvent(EVENTTYPE_AUTORETRY,
			{
				myPackage:myPackage
			}
		);
		this.dispatchEvent(ke);
	}
	
	//=============
	private function trace2(sTip:String){
		T.p("__________________"+sTip+"_______________");
	}
}//end of class
}